﻿using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
using UnityEngine;

public class CustomDataObj:IXmlSerializable
{
    public string name;
    public float height;
    public int age;
    public string city;

    //返回结构(默认返回null)
    public XmlSchema GetSchema()
    {
        return null;
    }

    //反序列化时 自动调用的方法
    public void ReadXml(XmlReader reader)
    {
        //实现反序列化的规则
        //1.读属性
        //this.name = reader["name"];
        //this.height = float.Parse(reader["height"]);
        //this.age = int.Parse(reader["age"]);
        //this.city = reader["city"];

        //2.读节点
        #region 方式一
        //reader.Read(); //这时是读到的name节点
        //reader.Read(); //这时是读到name包裹的内容
        //this.name = reader.Value;
        //reader.Read(); //这时读到的是尾部包裹节点

        //reader.Read();
        //reader.Read();
        //this.height = float.Parse(reader.Value);
        //reader.Read();

        //reader.Read();
        //reader.Read();
        //this.age = int.Parse(reader.Value);
        //reader.Read();

        //reader.Read();
        //reader.Read();
        //this.city = reader.Value;
        //reader.Read();
        #endregion

        #region 方式二
        //while (reader.Read())
        //{
        //    if (reader.NodeType == XmlNodeType.Element)
        //    {
        //        switch (reader.Name)
        //        {
        //            case "name":
        //                reader.Read();
        //                this.name = reader.Value;
        //                break;
        //            case "height":
        //                reader.Read();
        //                this.height = float.Parse(reader.Value);
        //                break;
        //            case "age":
        //                reader.Read();
        //                this.age = int.Parse(reader.Value);
        //                break;
        //            case "city":
        //                reader.Read();
        //                this.city = reader.Value;
        //                break;
        //        }
        //    }
        //}
        #endregion

        #region 读取包裹节点
        XmlSerializer sName = new XmlSerializer(typeof(string));
        XmlSerializer sHeight = new XmlSerializer(typeof(float));
        XmlSerializer sAge = new XmlSerializer(typeof(int));
        XmlSerializer sCity = new XmlSerializer(typeof(string));
        //跳过根节点
        reader.Read();
        reader.ReadStartElement("name");
        this.name = sName.Deserialize(reader).ToString();
        reader.ReadEndElement();

        reader.ReadStartElement("height");
        this.height = (float)sHeight.Deserialize(reader);
        reader.ReadEndElement();

        reader.ReadStartElement("age");
        this.age = (int)sAge.Deserialize(reader);
        reader.ReadEndElement();

        reader.ReadStartElement("city");
        this.city = sCity.Deserialize(reader).ToString();
        reader.ReadEndElement();

        #endregion

    }

    //序列化时 自动调用的方法
    public void WriteXml(XmlWriter writer)
    {
        //实现自定义序列化的规则
        //如果要自定序列化的规则 一定会用到 XmlWrite中的一些方法 来进行序列化
        //1.写属性
        //writer.WriteAttributeString("name", this.name != null ? this.name : "");
        //writer.WriteAttributeString("height", this.height.ToString());
        //writer.WriteAttributeString("age", this.age.ToString());
        //writer.WriteAttributeString("city", this.city);

        //2.写节点
        //writer.WriteElementString("name", this.name != null ? this.name : "");
        //writer.WriteElementString("height", this.height.ToString());
        //writer.WriteElementString("age", this.age.ToString());
        //writer.WriteElementString("city", this.city);

        //3.写包裹节点
        #region 方式一
        //writer.WriteStartElement("name");
        //writer.WriteElementString("string", this.name);
        //writer.WriteEndElement();

        //writer.WriteStartElement("height");
        //writer.WriteElementString("float", this.height.ToString());
        //writer.WriteEndElement();

        //writer.WriteStartElement("age");
        //writer.WriteElementString("int", this.age.ToString());
        //writer.WriteEndElement();

        //writer.WriteStartElement("city");
        //writer.WriteElementString("string", this.city);
        //writer.WriteEndElement();
        #endregion

        #region 方式二
        XmlSerializer sName = new XmlSerializer(typeof(string));
        writer.WriteStartElement("name");
        sName.Serialize(writer, this.name);
        writer.WriteEndElement();

        XmlSerializer sHeight = new XmlSerializer(typeof(float));
        writer.WriteStartElement("height");
        sHeight.Serialize(writer, this.height);
        writer.WriteEndElement();

        XmlSerializer sAge = new XmlSerializer(typeof(int));
        writer.WriteStartElement("age");
        sAge.Serialize(writer, this.age);
        writer.WriteEndElement();

        XmlSerializer sCity = new XmlSerializer(typeof(string));
        writer.WriteStartElement("city");
        sCity.Serialize(writer, this.city);
        writer.WriteEndElement();
        #endregion

    }
}

public class Lesson3 : MonoBehaviour
{
    void Start()
    {
        #region 知识一 IXmlSerializable是什么
        //让特殊类继承IxmlSerializable接口实现其中的方法即可
        //可以让一些不能被序列化和反序列化的特殊类能被处理
        //让特殊类继承IxmlSerializable接口实现其中的方法即可
        #endregion

        #region 知识二 自定义类实践
        CustomDataObj obj = new CustomDataObj();
        obj.name = "kitty";
        obj.height = 175.55f;
        obj.age = 25;
        obj.city = "重庆";

        string path = Application.persistentDataPath + "/CustomDataObj.xml";
        //序列化
        using (StreamWriter write = new StreamWriter(path))
        {
            //序列化翻译机器 
            XmlSerializer s = new XmlSerializer(typeof(CustomDataObj));
            //在序列化时 如果对象中的引用成员为空 那么xml里面是看不到字段的
            s.Serialize(write, obj);
        }
        //反序列化
        using (StreamReader reader = new StreamReader(path))
        {
            XmlSerializer s = new XmlSerializer(typeof(CustomDataObj));
            CustomDataObj data = s.Deserialize(reader) as CustomDataObj;
        }
        #endregion
    }
}
